﻿using System.Web.Mvc;
using System.Web.Routing;
using Nop.Core.Infrastructure;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Security;
using Nop.Web.Framework.Seo;
using System.Web;
using System;

namespace Nop.Web.CDN.Controllers
{
    [CheckAffiliate]
    [StoreClosed]
    [PublicStoreAllowNavigation]
    [LanguageSeoCode]
    [NopHttpsRequirement(SslRequirement.NoMatter)]
    [WwwRequirement]
    public abstract partial class BasePublicController : BaseController
    {
        /// <summary>
        /// if return false, nothing has changed, output 304 to client
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        public bool SetAutoEtag(HttpRequestBase request, HttpResponseBase response)
        {
            bool dateModified = false;
            bool eTagModified = false;

            string requestETagHeader = request.Headers["If-None-Match"] ?? string.Empty;
            string requestIfModifiedSinceHeader = request.Headers["If-Modified-Since"] ?? string.Empty;
            DateTime requestIfModifiedSince;
            DateTime.TryParse(requestIfModifiedSinceHeader, out requestIfModifiedSince);

            string responseETagHeader = response.Headers["ETag"] ?? string.Empty;
            string responseLastModifiedHeader = response.Headers["Last-Modified"] ?? string.Empty;
            DateTime responseLastModified;
            DateTime.TryParse(responseLastModifiedHeader, out responseLastModified);

            // First check for an etag match

            //Leave the default for eTagModified = false so that if we
            //don't get an ETag from the server we will rely on the fileDateModified only
            if (!String.IsNullOrEmpty(responseETagHeader))
            {
                // eTagModified==false, we will output 304.
                eTagModified = responseETagHeader.Equals(requestETagHeader, StringComparison.Ordinal) == false;
            }

            if (requestIfModifiedSince != DateTime.MinValue && responseLastModified != DateTime.MinValue)
            {
                responseLastModified = responseLastModified.ToUniversalTime();
                requestIfModifiedSince = requestIfModifiedSince.ToUniversalTime();

                if (responseLastModified > requestIfModifiedSince)
                {
                    TimeSpan diff = responseLastModified - requestIfModifiedSince;
                    if (diff > TimeSpan.FromSeconds(1))
                    {
                        dateModified = true;
                    }
                }
            }

            return (dateModified || eTagModified);
        }

        /// <summary>
        /// Set response etag.
        /// If this returns false you can short-circuit your code and just do res.end();
        /// </summary>
        /// <param name="request">http request</param>
        /// <param name="response">http reponse</param>
        /// <param name="eTag">etag string</param>
        /// <returns>false: nothing has changed, output 304 to client</returns>
        public bool SetEtagLastModified(HttpRequestBase request, HttpResponseBase response, DateTime date)
        {
            date = date.ToUniversalTime();
            var etag = date.ToString("yyyy:MM:dd:hh:mm:ss.fff");
            response.AppendHeader("Etag", etag);
            response.AppendHeader("Last-Modified", date.ToString());

            response.Cache.VaryByHeaders["If-None-Match"] = true;

            // the server cdn image has been changed. if return true.
            if (this.SetAutoEtag(request, response))
            {
                //tell client to cache
                response.Cache.SetCacheability(HttpCacheability.Public);
                response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
                //set lastModified.
                response.Cache.SetLastModified(date);

                //set age/expires so that client doesn't attempt to use cache
                response.Cache.SetMaxAge(new TimeSpan(0, 0, 0)); //max-age=0
                response.Cache.SetExpires(DateTime.Now.ToUniversalTime());

                return true;
            }
            //tell the client the image has not changed!
            return false;
        }

    }
}
